#include <stdio.h>
#include <inttypes.h>

/* typedef struct { */
/*   uint8_t sign; */
/*   int16_t exp; */
/*   // uint32_t sig; */
/*   uint32_t frac; */

/*   uint8_t is_nan; */
/*   uint8_t is_inf; */
/* } float32;                      /\* the intermediate format ?? *\/ */
/*  */


/* [0][b62].[b61]......[b0]  => the MSB shall be 0 to check overflow when add/sub/... */
typedef uint64_t fixed64;

/* the intermediate format is a common floating-point format */
typedef struct {
  uint8_t sign;
  int16_t exp;                  /* from -32768 ~ 32768 */
  fixed64 frac;                /* the fraction (contain the hidden '1') */

  uint8_t is_nan;
  uint8_t is_inf;
} float_t;                      /* the intermediate format ?? */




/* ignore the MSB */
int count_leading_zeros(fixed64 a)
{
  int i = 0;
  a = (a<<1) | 1;
  while( !(a & (1LL<<63)) )
    {
      a <<= 1;
      i++;
    }
  return i;
}

void normalize_fixed64(fixed64 *a, int16_t *exp)
{
  int cnt;
  cnt = count_leading_zeros(*a);
  *a <<= cnt;
  *exp = -cnt;
}


float_t float_to_float_t(float a)
{
  float_t f;
  int16_t biased_exp;
  uint32_t sig;
  fixed64 frac;
  uint32_t u = *((uint32_t *)&a);
  int16_t expdiff;
  
  f.sign = u>>31;
  biased_exp = (u>>23) & 0xff;
  sig = u & 0x7fffff;
  if(biased_exp == 0xff)
    {
      if(sig)
        f.is_nan = 1;
      else
        f.is_inf = 1;
    }
  else
    {
      if(biased_exp)            /* normal */
        frac = sig | 0x800000;
      else
        frac = sig;      /* 0 or subnormal */
      
      frac <<= (63-24);
      normalize_fixed64(&frac, &expdiff);
      f.frac = frac;
      f.exp = biased_exp - 127 + expdiff;
    }
  
  return f;
}


int main()
{
  float a;
  float_t ft;
  a = 3.1415926;
  
  ft = float_to_float_t(a);
  printf("%f => sign:%d,exp:%d,sig:%llx\n", a, ft.sign, ft.exp, ft.frac);
  

  
}
